<?php
// +----------------------------------------------------------------------
// | CoreThink [ Simple Efficient Excellent ]
// +----------------------------------------------------------------------
// | Copyright (c) 2014 http://www.thinkphp.cn/ All rights reserved.
// +----------------------------------------------------------------------
// |
// +----------------------------------------------------------------------
namespace app\attachment\controller;

use app\common\controller\Base;
use OSS\OssClient;
use OSS\Core\OssException;
use util\Logger;

/**
 * 阿里云存储对象上传
 * @author nagi
 */
class AliyuncsUpload extends Base
{
    private $bucket;
    private $ossClient;

    public function __construct($driver)
    {
        try {
            $this->bucket    = $driver['bucket'];
            $this->ossClient = new OssClient($driver['accessKey'], $driver['secretKey'], $driver['endpoint']);
        } catch (OssException $e) {
            trace($e->getMessage(), 'error');
            return;
        }
    }

    /**
     * 上传
     * @param null $info
     * @return array
     */
    public function upload($info = null)
    {
        if (empty($info)) {
            $info = $this->dealFiles($_FILES);
            $info = $info['file'];
        }

        try {
            //文件名
            $object = $info['md5'] . '.' . $info['ext'];
//            $object = $info['name'];
            //文件
            $filepath = $info['tmp_name'];
            //存储目录
            $date = date('Y-m-d', time());
            if (str_starts_with($info['type'], 'image/')) {
                $path = 'images/' . $date;
            } elseif (str_starts_with($info['type'], 'video/')) {
                $path = 'videos/' . $date;
            } else {
                $path = $date;
            }
            //判断是否存在文件夹，没有则创建
            $exist = $this->ossClient->doesObjectExist($this->bucket, $path);
            if (!$exist) {
                $this->ossClient->createObjectDir($this->bucket, $path);
            }
            //上传文件
            $oss_file = $path . '/' . $object;
            $size     = $info['size'];
            //当文件大于设置的上传切片大小时，进行切片上传
            if ($size > config('upload_slice_size')) {
                // 分片上传参数设置
                $options = [
                    'partSize'         => intval(config('upload_slice_part')), //每个分片大小
                    'taskNum'          => intval(config('upload_slice_task')), //并发任务数量
                    'enableCheckpoint' => true,   // 是否启用断点续传，默认关闭
                ];
                // 开始分片上传
                $this->ossClient->multiuploadFile($this->bucket, $oss_file, $filepath, $options);
            } else {
                $this->ossClient->uploadFile($this->bucket, $oss_file, $filepath);
            }
            $result = ['code' => 0, 'msg' => '上传成功', 'name' => $object, 'url' => $oss_file];
        } catch (\Exception $e) {
            trace($e->getMessage(), 'error');
            $result = ['code' => -1, 'msg' => '上传失败', 'data' => null];
        }

        return $result;
    }

    /**
     * 上传本地文件
     * @param string $filename 文件名
     * @param string $filepath 文件目录
     * @param string $file 本地文件
     * @return string
     * @throws \Exception
     */
    public function upload_local(string $filename, string $filepath, string $file)
    {
        try {
            //文件名
            $object = $filename;
            $type   = mime_content_type($file);
            //存储目录
            if (str_starts_with($type, 'image/')) {
                $path = 'images/' . $filepath;
            } elseif (str_starts_with($type, 'video/')) {
                $path = 'videos/' . $filepath;
            } else {
                $path = $filepath;
            }
            //判断是否存在文件夹，没有则创建
            $exist = $this->ossClient->doesObjectExist($this->bucket, $path);
            if (!$exist) {
                $this->ossClient->createObjectDir($this->bucket, $path);
            }
            //上传文件
            $oss_file = $path . '/' . $object;
            $size     = filesize($file);
            //当文件大于设置的上传切片大小时，进行切片上传
            if ($size > config('upload_slice_size')) {
                // 分片上传参数设置
                $options = [
                    'partSize'         => intval(config('upload_slice_part')), //每个分片大小
                    'taskNum'          => intval(config('upload_slice_task')), //并发任务数量
                    'enableCheckpoint' => true,   // 是否启用断点续传，默认关闭
                ];
                // 开始分片上传
                $this->ossClient->multiuploadFile($this->bucket, $oss_file, $file, $options);
            } else {
                $this->ossClient->uploadFile($this->bucket, $oss_file, $file);
            }
            return $oss_file;
        } catch (\Exception $e) {
            Logger::error('上传失败：' . $e->getMessage());
            throw new \Exception('上传失败');
        }
    }

    /**
     * 删除文件
     * @param string $object 对象名
     * @param string $driver 上传驱动
     * @return array
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public function delete($object = '', $driver = '')
    {
        if (empty($object)) {
            $object = $this->request->param('object');
        }

        try {
            $this->ossClient->deleteObject($this->bucket, $object);

            //删除附件记录
            deleteModel('attachment', ['path' => $object, 'driver' => $driver]);

            $result = ['code' => 0, 'msg' => '删除成功'];
        } catch (OssException $e) {
            trace($e->getMessage(), 'error');
            $result = ['code' => -1, 'msg' => '删除失败'];
        }

        return $result;
    }

    /**
     * 转换上传文件数组变量为正确的方式
     * @access private
     * @param array $files 上传的文件变量
     * @return array
     */
    private function dealFiles($files)
    {
        $fileArray = array();
        $n         = 0;
        foreach ($files as $key => $file) {
            if (is_array($file['name'])) {
                $keys  = array_keys($file);
                $count = count($file['name']);
                for ($i = 0; $i < $count; $i++) {
                    $fileArray[$n]['key'] = $key;
                    foreach ($keys as $_key) {
                        $fileArray[$n][$_key] = $file[$_key][$i];
                    }
                    $n++;
                }
            } else {
                $fileArray = $files;
                break;
            }
        }
        return $fileArray;
    }

}
